/**
 * Tool Factory
 * 
 * Utilities for creating and managing tools for Claude Agent SDK
 * Based on: https://docs.claude.com/en/api/agent-sdk/custom-tools
 */

import { tool, createSdkMcpServer } from '@anthropic-ai/claude-agent-sdk';
import { z } from 'zod';
import type { ToolDefinition, CallToolResult } from '@/types';
import { logger } from '@/utils/logger';

/**
 * Create a tool using the Claude Agent SDK tool() helper
 * 
 * @param definition - Tool definition
 * @returns Tool instance
 */
export function createTool(definition: ToolDefinition) {
  logger.info(`Creating tool: ${definition.name}`);
  
  return tool(
    definition.name,
    definition.description,
    definition.inputSchema,
    definition.handler
  );
}

/**
 * Create an SDK MCP server with custom tools
 * 
 * SDK MCP servers run in-process and are more efficient than external MCP servers.
 * They are perfect for built-in tools that don't require external processes.
 * 
 * @param name - Server name
 * @param tools - Array of tool definitions
 * @returns SDK MCP server instance
 */
export function createToolServer(name: string, tools: ToolDefinition[]) {
  logger.info(`Creating SDK MCP server: ${name} with ${tools.length} tools`);
  
  const toolInstances = tools.map(createTool);
  
  return createSdkMcpServer({
    name,
    version: '1.0.0',
    tools: toolInstances,
  });
}

/**
 * Tool registry for managing all available tools
 */
export class ToolRegistry {
  private tools: Map<string, ToolDefinition> = new Map();
  private servers: Map<string, any> = new Map();

  /**
   * Register a tool
   */
  registerTool(definition: ToolDefinition): void {
    logger.info(`Registering tool: ${definition.name}`);
    this.tools.set(definition.name, definition);
  }

  /**
   * Register multiple tools
   */
  registerTools(definitions: ToolDefinition[]): void {
    definitions.forEach(def => this.registerTool(def));
  }

  /**
   * Get a tool by name
   */
  getTool(name: string): ToolDefinition | undefined {
    return this.tools.get(name);
  }

  /**
   * Get all registered tools
   */
  getAllTools(): ToolDefinition[] {
    return Array.from(this.tools.values());
  }

  /**
   * Create and register an SDK MCP server
   */
  createServer(name: string, toolNames: string[]): any {
    const tools = toolNames
      .map(name => this.getTool(name))
      .filter((tool): tool is ToolDefinition => tool !== undefined);

    if (tools.length === 0) {
      throw new Error(`No tools found for server: ${name}`);
    }

    const server = createToolServer(name, tools);
    this.servers.set(name, server);
    
    logger.info(`Created SDK MCP server: ${name} with ${tools.length} tools`);
    return server;
  }

  /**
   * Get a server by name
   */
  getServer(name: string): any {
    return this.servers.get(name);
  }

  /**
   * Get all registered servers
   */
  getAllServers(): Map<string, any> {
    return this.servers;
  }

  /**
   * Get server configuration for Claude Agent SDK
   * 
   * Returns a configuration object that can be passed to the `mcpServers` option
   */
  getServerConfig(): Record<string, any> {
    const config: Record<string, any> = {};
    
    this.servers.forEach((server, name) => {
      config[name] = {
        type: 'sdk',
        instance: server,
      };
    });
    
    return config;
  }
}

/**
 * Global tool registry instance
 */
export const toolRegistry = new ToolRegistry();

/**
 * Helper function to create a simple text result
 */
export function createTextResult(text: string): CallToolResult {
  return {
    content: [
      {
        type: 'text',
        text,
      },
    ],
  };
}

/**
 * Helper function to create an error result
 */
export function createErrorResult(error: Error | string): CallToolResult {
  const message = error instanceof Error ? error.message : error;
  return createTextResult(`Error: ${message}`);
}

